package com.thinkit.security.config;
import com.thinkit.security.custom.CustomJwtAuthenticationFilter;
import com.thinkit.security.custom.CustomJwtHandler;
import com.thinkit.security.custom.CustomSecurityMetadataSourceSource;
import com.thinkit.utils.properties.PermitAllUrlProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.authentication.TokenExtractor;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Configuration
@Component
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true)
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

	@Autowired
	private DefaultTokenServices tokenServices;

	@Autowired
	TokenExtractor tokenExtractor;

	@Resource
	JwtTokenStore tokenStore;

	@Autowired
    AuthenticationEntryPoint authenticationEntryPoint;

	@Autowired
    AccessDeniedHandler accessDeniedHandler;

	@Autowired
    AccessDecisionManager accessDecisionManager;

	@Autowired
	CustomSecurityMetadataSourceSource customSecurityMetadataSource;

	@Autowired
    CustomJwtHandler customJwtHandler;

	@Autowired
	PermitAllUrlProperties permitAllUrlProperties;

	@Value("${spring.application.name}")
	private String application;

	@Override
	public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
		resources.tokenServices(tokenServices).tokenExtractor(tokenExtractor)
		.authenticationEntryPoint(authenticationEntryPoint)
		.accessDeniedHandler(accessDeniedHandler);
	}

	@Override
	public void configure(HttpSecurity http) throws Exception {
		List<String> permitAllEndpointList = permitAllUrlProperties.authcs(application);
		AuthcPathRequestMatcher authcPathRequestMatcher = new AuthcPathRequestMatcher(permitAllUrlProperties,application);
		CustomJwtAuthenticationFilter filter = new CustomJwtAuthenticationFilter(authcPathRequestMatcher,tokenStore,customJwtHandler);
		customSecurityMetadataSource.setRequestMatcher(authcPathRequestMatcher);
		http.authorizeRequests().antMatchers(permitAllEndpointList.toArray(new String[permitAllEndpointList.size()]))
		.permitAll().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
		@Override
		public <O extends FilterSecurityInterceptor> O postProcess(O object) {
			object.setAccessDecisionManager(accessDecisionManager);
			object.setSecurityMetadataSource(customSecurityMetadataSource);
			return object;
		}
		}).and().addFilterBefore(filter, FilterSecurityInterceptor.class);
	}
    

}
